package team

import (
	"fmt"
	"sanguo/cluster"
	"sanguo/node/common/orderMap"
	"sanguo/node/common/transaction"
	"sanguo/node/node_team"
	"sanguo/node/node_team/com"
	cs_msg "sanguo/protocol/cs/message"
	ss_msg "sanguo/protocol/ss/message"
	ss_rpc "sanguo/protocol/ss/rpc"
	"sanguo/rpc/teamToGameMsg"
	"time"

	"github.com/golang/protobuf/proto"
	"github.com/sniperHW/kendynet"
	"github.com/sniperHW/kendynet/event"
)

type TeamManager struct {
	RoleToTeam   map[uint64]*Team
	orderMapTeam *orderMap.OrderMap
	processQueue *event.EventQueue
}

var TeamMgr TeamManager

func (this *TeamManager) PostTask(task func()) {
	this.processQueue.Post(task)
}

func (this *TeamManager) GetTeamCount() int {
	return this.orderMapTeam.Len()
}

func (this *TeamManager) GetTeam(teamID uint64) *Team {
	_team := this.orderMapTeam.GetValueByKey(teamID)
	if _team == nil {
		return nil
	} else {
		return _team.(*Team)
	}
}

func (this *TeamManager) GetTeamByIdx(idx int) *Team {
	_team := this.orderMapTeam.GetValueByIdx(idx)
	if _team == nil {
		return nil
	} else {
		return _team.(*Team)
	}
}

func (this *TeamManager) AddTeam(teamObj *Team) {
	this.orderMapTeam.Add(teamObj.TeamID, teamObj)
}

func (this *TeamManager) DelTeam(teamID uint64) {
	//删除数组元素
	this.orderMapTeam.Del(teamID)
}

func (this *Team) KickRole(role *Role) {
	req := &ss_rpc.TeamToGameMsgReq{
		MsgType: ss_rpc.TTGType(ss_rpc.TTGType_Kick_Role).Enum(),
		RoleID:  proto.Uint64(role.RoleID),
		UserID:  proto.String(role.UserID),
	}
	teamToGameMsg.AsynCall(role.Game, req, transaction.TransTimeoutMs, func(respMsg *ss_rpc.TeamToGameMsgResp, err error) {
		if nil == err && respMsg.GetOk() == 1 {
			this.DelRole(role.RoleID)
			UpdateTeamToClients(this)

			delete(TeamMgr.RoleToTeam, role.RoleID)

			kick := &cs_msg.KickTeammateToC{}
			role.SendToClient(kick)
			node_team.Infoln("Kick Ok", role.RoleID)
		} else {
			node_team.Infoln("Kick fail", err)
		}
	})
}

func (this *Team) tick(now time.Time) {
	if now.Unix() > this.NextHeartbeat && this.Status != com.TeamStatus_Battle {
		node_team.Infof("TeamID:%d heartbeat timeout", this.TeamID)
		for _, r := range this.GetRoles() {
			this.KickRole(r)
		}
		TeamMgr.DelTeam(this.TeamID)
	} else {
		if this.Fight != nil {
			if now.Unix() > this.Fight.DestoryTime {
				this.Status = com.TeamStatus_Safe
				this.Fight = nil
			}
		}
	}

	//清除申请超时角色
	for roleID, aRole := range this.ApplyRoles {
		if now.Unix() > aRole.DestoryTime {
			delete(this.ApplyRoles, roleID)
		}
	}

	//离线玩家处理
	if this.Status != com.TeamStatus_Battle {
		for _, role := range this.GetRoles() {
			if role.Status == com.RoleStatus_Offline {
				if role.CheckOffLineKick(now) {
					this.KickRole(role)
				}
			}
		}
	}

	//战斗

}

func onHeartbeat(session kendynet.StreamSession, msg proto.Message) {
	req := msg.(*ss_msg.HeartbeatTeam)

	TeamMgr.PostTask(func() {
		_team := TeamMgr.GetTeam(req.GetTeamID())
		if _team != nil && _team.Header == req.GetRoleID() {
			now := time.Now().Unix()
			_team.NextHeartbeat = now + com.HeartBeatTimeout
			fmt.Println(_team.TeamID, _team.GetRole(_team.Header).UserID, "OnHeartBeat")
		}
	})
}

func init() {
	cluster.Register(&ss_msg.HeartbeatTeam{}, func(session kendynet.StreamSession, msg proto.Message) {
		onHeartbeat(session, msg)
	})

	TeamMgr = TeamManager{
		RoleToTeam:   map[uint64]*Team{},
		orderMapTeam: orderMap.NewOrderMap(),
		processQueue: event.NewEventQueue(),
	}
	go func() {
		TeamMgr.processQueue.Run()
	}()

	go func() {
		for {
			now := time.Now()
			time.Sleep(time.Millisecond * 500)
			for _, v := range TeamMgr.orderMapTeam.OrderRead() {
				t := v.(*Team)
				TeamMgr.PostTask(func() { t.tick(now) })
			}
		}
	}()
}
